
package org.zfes.snowier.cloud.zbss.pmp.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.zfes.snowier.core.data.DataSet;
import org.zfes.snowier.core.exceptions.ServiceLogicalException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.zfes.snowier.core.util.ZBeanUtil;
import org.zfes.snowier.core.util.ZDateUtil;
import org.zfes.snowier.core.util.ZObjectUtil;
import org.zfes.snowier.core.util.ZAlert;
import org.zfes.snowier.core.util.ZAssert;
import org.zfes.snowier.common.dao.params.ParamMap;
import org.zfes.snowier.cloud.zbss.pmp.service.IPmpCloudMemberService;
import org.zfes.snowier.cloud.zbss.pmp.service.IPmpDifficultyScoreService;
import org.zfes.snowier.cloud.zbss.pmp.service.IPmpProjectService;
import org.zfes.snowier.cloud.zbss.pmp.service.IPmpProjectVersionService;
import org.zfes.snowier.cloud.zbss.pmp.service.IPmpRequiresService;
import org.zfes.snowier.cloud.zbss.pmp.service.IPmpTasksRecordService;
import org.zfes.snowier.cloud.zbss.pmp.service.IPmpTasksService;
import org.zfes.snowier.cloud.zbss.pmp.service.IPmpTasksSplitService;
import org.zfes.snowier.cloud.zbss.pmp.dao.PmpTasksMapper;
import org.zfes.snowier.cloud.zbss.pmp.dto.PmpTasksCreateDto;
import org.zfes.snowier.cloud.zbss.pmp.dto.PmpTasksDetailDto;
import org.zfes.snowier.cloud.zbss.pmp.dto.PmpTasksSplitDto;
import org.zfes.snowier.cloud.zbss.pmp.dto.PmpTasksSubmitDto;
import org.zfes.snowier.cloud.zbss.pmp.dto.PmpTasksUpdateDto;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpCloudMember;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpDifficultyScore;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpProject;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpProjectVersion;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpRequires;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpTasks;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpTasksRecord;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpTasksSplit;

import java.util.stream.Stream;

@Service
public class PmpTasksServiceImpl implements IPmpTasksService {
	@Autowired
	private PmpTasksMapper pmpTasksMapper;

	@Autowired
	private IPmpCloudMemberService pmpCloudMemberService;
	@Autowired
	private IPmpProjectService pmpProjectService;
	@Autowired
	private IPmpRequiresService pmpRequiresService;
	@Autowired
	private IPmpDifficultyScoreService pmpDifficultyScoreService;

	@Autowired
	private IPmpProjectVersionService pmpProjectVersionService;

	@Autowired
	private IPmpTasksSplitService pmpTasksSplitService;
	@Autowired
	private IPmpTasksRecordService pmpTasksRecordService;

	@Transactional(rollbackFor = Exception.class)
	@Override
	public Long createPmpTasks(Long creatorUserId, PmpTasksCreateDto tasksCreateDto) {
		ZBeanUtil.validateBean(tasksCreateDto);

		PmpTasks pmpTasks = new PmpTasks();

		ZBeanUtil.copy(tasksCreateDto, pmpTasks, true);

		PmpProject pmpProject = pmpProjectService.loadPmpProjectById(tasksCreateDto.getProjectId()).orElseThrow(() -> ZAlert.newSLE("未查询到项目信息"));
		ZAssert.equals(pmpProject.getStatus(), Byte.valueOf("1"), "项目已经删除或者结束");
		

		//#1未指派,2未开始,3进行中,4已提交,5被驳回,6已完成,-1已删除#
		if (ZObjectUtil.isNotNull(tasksCreateDto.getChargeUserId())) {
			PmpCloudMember chargeUser = pmpCloudMemberService.loadPmpCloudMemberById(pmpTasks.getChargeUserId()).orElseThrow(() -> ZAlert.newSLE("未查询到该用户"));
			ZAssert.equals(chargeUser.getStatus(), Byte.valueOf("1"), "负责人用户状态错误");
			pmpTasks.setChargeUserName(chargeUser.getUserName());
			pmpTasks.setStatus(Byte.valueOf("1"));

		}else {
			pmpTasks.setStatus(Byte.valueOf("1"));
		}
			
		PmpCloudMember creator = pmpCloudMemberService.loadPmpCloudMemberById(creatorUserId).orElseThrow(() -> ZAlert.newSLE("未查询到当前用户"));
		ZAssert.equals(creator.getStatus(), Byte.valueOf("1"), "创建人用户状态错误");

		pmpTasks.setCreatorUserId(creator.getId());
		pmpTasks.setCreatorUserName(creator.getUserName());
		
		if (Byte.valueOf("1").equals(tasksCreateDto.getFromRequire())) {
			PmpRequires requires = pmpRequiresService.loadPmpRequiresById(tasksCreateDto.getRequireId()).orElseThrow(() -> ZAlert.newSLE("未查询到所选取的需求"));
			pmpTasks.setRequireId(requires.getId());
		}

		if (ZObjectUtil.isNotNull(tasksCreateDto.getProjectVersionId())) {
			PmpProjectVersion projectVersion = pmpProjectVersionService.loadPmpProjectVersionById(tasksCreateDto.getProjectVersionId()).orElseThrow(() -> ZAlert.newSLE("未查询到选择版本信息"));
			ZAssert.equals(projectVersion.getStatus(), Byte.valueOf("1"), "当前版本已禁用或者删除");
			pmpTasks.setProjectVersionId(projectVersion.getId()).setProjectVersionName(projectVersion.getVersion());
		}else {
			pmpTasks.setProjectVersionId(pmpProject.getVersionId()).setProjectVersionName(pmpProject.getVersionName());
		}

		PmpDifficultyScore difScore = pmpDifficultyScoreService .loadPmpDifficultyScoreById(tasksCreateDto.getDifficultyScoreId()) .orElseThrow(() -> ZAlert.newSLE("难度配置错误"));
		pmpTasks.setDifficultyScore(difScore.getScore());
		pmpTasks.setDifficultyScoreId(difScore.getId());
		pmpTasks.setDifficultyScoreName(difScore.getName());
		
		pmpTasks.setWorkHours(Integer.valueOf("0"));
		pmpTasks.setProgress(Byte.valueOf("0"));
		pmpTasks.setExpired(Byte.valueOf("1"));//#1正常,2已超时#
		pmpTasks.setCreatetime(ZDateUtil.newDate());
		pmpTasks.setUpdatetime(ZDateUtil.newDate());

		
		pmpTasksMapper.insertSelective(pmpTasks);

		return pmpTasks.getId();
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void updatePmpTasks(PmpTasksUpdateDto tasksUpdateDto) {

		ZBeanUtil.validateBean(tasksUpdateDto);
		PmpTasks pmpTasks = loadPmpTasksById(tasksUpdateDto.getId()).orElseThrow(() -> ZAlert.newSLE("未查询到数据"));

		ZBeanUtil.copy(tasksUpdateDto, pmpTasks, true);

		ZBeanUtil.setUpdatedInfo(pmpTasks);
		pmpTasksMapper.updateByPrimaryKeySelective(pmpTasks);
	}

	@Transactional(rollbackFor = Exception.class, readOnly = true)
	@Override
	public Optional<PmpTasks> loadPmpTasksById(Long id) {
		if (id != null) {
			return Optional.ofNullable(pmpTasksMapper.selectByPrimaryKey(id));
		}
		return Optional.empty();
	}

	// D#1未指派,2未开始,3进行中,4已提交,5被驳回,6已完成,-1已删除#
	@Transactional(rollbackFor = Exception.class)
	@Override
	public void setPmpTasksStatus(Long id, Byte status) {
		ZAssert.notNull(id, "请选择要操作的数据");
		ZAssert.notNull(status, "状态参数错误");
		if (!Stream.of(new Byte[] { -1, 1, 2, 3, 4, 5, 6, -1 }).anyMatch(val -> val.equals(status))) {
			ZAlert.serviceLogicalError("状态参数错误");
		}
		PmpTasks tasks = loadPmpTasksById(id).orElseThrow(() -> new ServiceLogicalException("未查找到该任务"));

		ZBeanUtil.setUpdatedInfo(tasks);
		tasks.setStatus(status);
		pmpTasksMapper.updateByPrimaryKeySelective(tasks);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public int updateAssignHours(Long id, Integer assignHours) {
		ZAssert.notNull(id, "请选择数据");
		ZAssert.bigOrEqThanZero(assignHours, "分配时间必须大于0", "请输入正确的分配时间");

		PmpTasks tasks = loadPmpTasksById(id).orElseThrow(() -> new ServiceLogicalException("未查找到该任务"));
		if (!Stream.of(new Byte[] { 1, 2, 3, 4, 5 }).anyMatch(val -> val.equals(tasks.getStatus()))) {
			ZAlert.serviceLogicalError("任务当前状态不可指派时间");
		} // 任务状态_D#1未指派,2未开始,3进行中,4已提交,5被驳回,6已完成,-1已删除

		return pmpTasksMapper.updateAssignHours(id, assignHours);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public int updateWorkHours(Long id, Integer workHours) {
		ZAssert.notNull(id, "请选择数据");
		ZAssert.bigOrEqThanZero(workHours, "分配时间必须大于0", "请输入正确的工作时间");

		PmpTasks tasks = loadPmpTasksById(id).orElseThrow(() -> new ServiceLogicalException("未查找到该任务"));
		if (!Stream.of(new Byte[] { 3, 4, 5 ,6}).anyMatch(val -> val.equals(tasks.getStatus()))) {
			ZAlert.serviceLogicalError("任务当前状态不可添加工时");
		} // 任务状态_D#1未指派,2未开始,3进行中,4已提交,5被驳回,6已完成,-1已删除

		return pmpTasksMapper.updateWorkHours(id,workHours);
	}
	@Transactional(rollbackFor = Exception.class)
	@Override
	public int updateTaskName(Long id, String taskName) {
		ZAssert.notNull(id, "请选择数据");
		ZAssert.hasText(taskName, "任务名不能为空");

		PmpTasks tasks = loadPmpTasksById(id).orElseThrow(() -> new ServiceLogicalException("未查找到该任务"));

		if (!Stream.of(new Byte[] { 1, 2, 3, 4, 5 }).anyMatch(val -> val.equals(tasks.getStatus()))) {
			ZAlert.serviceLogicalError("任务当前状态不可更新任务名");
		} // 任务状态_D#1未指派,2未开始,3进行中,4已提交,5被驳回,6已完成,-1已

		return pmpTasksMapper.updateTaskName(id, taskName);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public int updateExpiryTime(Long id, Date expiryTime) {
		ZAssert.notNull(id, "请选择数据");
		ZAssert.notNull(expiryTime, "任务截止日期不能为空");

		PmpTasks tasks = loadPmpTasksById(id).orElseThrow(() -> new ServiceLogicalException("未查找到该任务"));

		if (!Stream.of(new Byte[] { 1, 2, 3, 4, 5 }).anyMatch(val -> val.equals(tasks.getStatus()))) {
			ZAlert.serviceLogicalError("任务当前状态不可更新任务截止时间");
		} // 任务状态_D#1未指派,2未开始,3进行中,4已提交,5被驳回,6已完成,-1已

		return pmpTasksMapper.updateExpiryTime(id, expiryTime);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public int updateExpired(Long id, Byte expired) {
		ZAssert.notNull(id, "请选择数据");
		if (!Stream.of(new Byte[] { 1, 2 }).anyMatch(val -> val.equals(expired))) {
			ZAlert.serviceLogicalError("是否超时参数错误");
		}

		PmpTasks tasks = loadPmpTasksById(id).orElseThrow(() -> new ServiceLogicalException("未查找到该任务"));
		if (!Stream.of(new Byte[] { 3, 4, 5 }).anyMatch(val -> val.equals(tasks.getStatus()))) {
			ZAlert.serviceLogicalError("任务当前状态不可更新是否延期");
		} // 任务状态_D#1未指派,2未开始,3进行中,4已提交,5被驳回,6已完成,-1已

		return pmpTasksMapper.updateExpired(id, expired);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public int updateVersion(Long id, Long versionId) {
		ZAssert.notNull(id, "请选择数据");
		ZAssert.notNull(versionId, "请选择版本");
		PmpProjectVersion version = pmpProjectVersionService.loadPmpProjectVersionById(versionId)
				.orElseThrow(() -> ZAlert.newSLE("未查询到选择版本信息"));
		ZAssert.equals(version.getStatus(), Byte.valueOf("1"), "当前版本已禁用或者删除");

		PmpTasks tasks = loadPmpTasksById(id).orElseThrow(() -> new ServiceLogicalException("未查找到该任务"));

		if (!Stream.of(new Byte[] { 1, 2, 3 }).anyMatch(val -> val.equals(tasks.getStatus()))) {
			ZAlert.serviceLogicalError("任务当前状态不可更新任务版本");
		} // 任务状态_D#1未指派,2未开始,3进行中,4已提交,5被驳回,6已完成,-1已

		return pmpTasksMapper.updateVersion(id, version.getId(), version.getVersion());
	}

	@Transactional(rollbackFor = Exception.class, readOnly = true)
	@Override
	public DataSet loadPmpTasksDataSet(Map<String, Object> params) {
		ParamMap pm = ParamMap.filterParam(params);
		DataSet ds = DataSet.newDS2(pmpTasksMapper.selectListCount(pm), pmpTasksMapper.selectMapListPage(pm));
		return ds;
	}

	@Transactional(rollbackFor = Exception.class, readOnly = true)
	@Override
	public List<PmpTasks> loadPmpTasksByProjectId(Long projectId) {
		ZAssert.notNull(projectId, "请选择数据");
		PmpProject project = pmpProjectService.loadPmpProjectById(projectId)
				.orElseThrow(() -> new ServiceLogicalException("未查找到该项目"));
		ZAssert.notEquals(project.getStatus(), Byte.valueOf("-1"), "该项目已被删除");

		return pmpTasksMapper.selecTasksByProjectId(projectId);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public int updateDifficultyScore(Long id, Long difficultyScoreId) {
		ZAssert.notNull(id, "请选择要操作的任务");
		ZAssert.notNull(difficultyScoreId, "请选择难度系数");

		PmpDifficultyScore difficultyScore = pmpDifficultyScoreService.loadPmpDifficultyScoreById(difficultyScoreId).orElseThrow(() -> new ServiceLogicalException("未查找到该难度系数"));
		ZAssert.equals(difficultyScore.getStatus(), Byte.valueOf("1"), "该难度系数状态错误");

		PmpTasks tasks = loadPmpTasksById(id).orElseThrow(() -> new ServiceLogicalException("未查找到该任务"));

		if (!Stream.of(new Byte[] { 1, 2, 3, 4, 5 }).anyMatch(val -> val.equals(tasks.getStatus()))) {
			ZAlert.serviceLogicalError("任务当前状态不可更新任务难度系数");
		} // 任务状态_D#1未指派,2未开始,3进行中,4已提交,5被驳回,6已完成,-1已

		return pmpTasksMapper.updateDifficultyScore(id, difficultyScoreId, difficultyScore.getScore(),difficultyScore.getName());
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void setPmpTasksChargeUser(Long id, Long chargeUserId) {
		ZAssert.notNull(id, "请选择要操作的任务");
		ZAssert.notNull(chargeUserId, "请选择任务负责人");

		PmpTasks tasks = loadPmpTasksById(id).orElseThrow(() -> new ServiceLogicalException("未查找到该任务"));

		if (!Stream.of(new Byte[] { 1, 2, 3 }).anyMatch(val -> val.equals(tasks.getStatus()))) {
			ZAlert.serviceLogicalError("任务当前状态不可更新负责人");
		} // 任务状态_D#1未指派,2未开始,3进行中,4已提交,5被驳回,6已完成,-1已

		PmpCloudMember member = pmpCloudMemberService.loadPmpCloudMemberById(chargeUserId) .orElseThrow(() -> new ServiceLogicalException("未查找到该用户"));
		ZAssert.equals(member.getStatus(), Byte.valueOf("1"), "用户当前状态错误");

		Byte sta=null;
		if (tasks.getStatus().equals(Byte.valueOf("1"))) {
			sta=Byte.valueOf("2");
		}
		pmpTasksMapper.updateChargeUser(id,chargeUserId,member.getUserName(),sta);
		
		
			
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void submitTasks(Long userId, PmpTasksSubmitDto pmpTasksSubmitDto) {

		ZAssert.notNull(pmpTasksSubmitDto.getId(), "请选择任务");
		ZAssert.bigOrEqThanZero(pmpTasksSubmitDto.getWorkHours(), "请输入投入工时", "投入工时参数错误");
		ZAssert.bigOrEqThanZero(pmpTasksSubmitDto.getProgress(), "请提交进度", "进参数错误");

		 
		PmpTasks tasks = loadPmpTasksById(pmpTasksSubmitDto.getId()).orElseThrow(() -> new ServiceLogicalException("未查找到该任务"));
		if(tasks.getProgress()>=100&&(Byte.valueOf("4").equals(tasks.getStatus()) ||Byte.valueOf("6").equals(tasks.getStatus())||Byte.valueOf("-1").equals(tasks.getStatus())||Byte.valueOf("1").equals(tasks.getStatus()))) {
			ZAlert.serviceLogicalError("任务当前状态不允许提交");
		}
		//Assert.isTrue(Stream.of(new Byte[] { 3, 4, 5 }).anyMatch(val -> val.equals(tasks.getStatus())), "任务当前状态不允许提交");
		// 任务状态_D#1未指派,2未开始,3进行中,4已提交,5被驳回,6已完成,-1已

		ZAssert.equals(userId, tasks.getChargeUserId(), "该任务未指派给当前用户");

		// 任务更新
		if (ZObjectUtil.isNotNull(pmpTasksSubmitDto.getIsSumitTask())
				&& Byte.valueOf("1").equals(pmpTasksSubmitDto.getIsSumitTask())) {
			tasks.setStatus(Byte.valueOf("4"));
			ZAssert.equals(pmpTasksSubmitDto.getProgress(), Byte.valueOf("100"), "完成进度不是100%");
		}

		ZBeanUtil.setUpdatedInfo(tasks);
		tasks.setWorkHours(pmpTasksSubmitDto.getWorkHours()).setProgress(pmpTasksSubmitDto.getProgress());
		pmpTasksMapper.updateByPrimaryKeySelective(tasks);

		// 添加至任务记录表
		PmpTasksRecord tasksRecord = new PmpTasksRecord().setChargeUserId(userId)
				.setChargeUserName(tasks.getChargeUserName()).setNowProgress(pmpTasksSubmitDto.getProgress())
				.setTaskId(pmpTasksSubmitDto.getId()).setWorkHours(pmpTasksSubmitDto.getWorkHours())
				.setWorkRemark(pmpTasksSubmitDto.getRemark()).setCreatetime(ZDateUtil.newDate());
		pmpTasksRecordService.createPmpTasksRecord(tasksRecord);

	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void addOnesplitPmpTasks(Long splitUserId, Long taskId, PmpTasksSplitDto splitDto) {
		ZAssert.notNull(taskId, "请选择要拆分的任务");
		ZAssert.notEmpty(splitDto, "请选择拆分出的任务");
		ZBeanUtil.validateBean(splitDto);
		PmpTasks pmpTasks = loadPmpTasksById(taskId).orElseThrow(() -> ZAlert.newSLE("未查询到数据"));

		Assert.isTrue(Stream.of(new Byte[] { 1, 2, 3, 4, 5 }).anyMatch(val -> val.equals(pmpTasks.getStatus())),
				"任务当前状态不允许拆分");
		// 任务状态_D#1未指派,2未开始,3进行中,4已提交,5被驳回,6已完成,-1已

		int restHours = pmpTasks.getAssignHours();

		restHours -= splitDto.getAssignHours();

		PmpTasksCreateDto tasksCreateDto = new PmpTasksCreateDto();

		ZBeanUtil.copy(splitDto, tasksCreateDto, true);
		tasksCreateDto.setProjectId(pmpTasks.getProjectId());

		tasksCreateDto.setFromRequire(pmpTasks.getFromRequire());

		tasksCreateDto.setRequireId(pmpTasks.getRequireId());

		// 优先级继承
		tasksCreateDto.setPriority(pmpTasks.getPriority());

		Long newTaskId = createPmpTasks(splitUserId, tasksCreateDto);

		// 任务拆分表
		PmpTasksSplit tasksSplit = new PmpTasksSplit();
		tasksSplit.setCreatorUserId(splitUserId).setChargeUserId(tasksCreateDto.getChargeUserId())
				.setNewTaskId(newTaskId).setOriginTaskId(taskId);

		if (ZObjectUtil.isNotNull(tasksCreateDto.getChargeUserId())) {
			PmpCloudMember chargeUser = pmpCloudMemberService.loadPmpCloudMemberById(tasksSplit.getChargeUserId())
					.orElseThrow(() -> ZAlert.newSLE("未查询到该用户"));
			ZAssert.equals(chargeUser.getStatus(), Byte.valueOf("1"), "负责人用户状态错误");
			tasksSplit.setChargeUserName(chargeUser.getUserName());
		}
		PmpCloudMember createUser = pmpCloudMemberService.loadPmpCloudMemberById(splitUserId)
				.orElseThrow(() -> ZAlert.newSLE("未查询到该用户"));
		ZAssert.equals(createUser.getStatus(), Byte.valueOf("1"), "创建人用户状态错误");
		tasksSplit.setCreatorUserName(createUser.getUserName());
        tasksSplit.setCreatetime(ZDateUtil.newDate());
	    
		pmpTasksSplitService.createPmpTasksSplit(tasksSplit);

		pmpTasksMapper.updateAssignHours(taskId, restHours);

	}

	//#1未指派,2未开始,3进行中,4已提交,5被驳回,6已完成,-1已删除#
	@Transactional(rollbackFor = Exception.class)
	@Override
	public int checkTask(Long id, Byte isOk, String rejectResaon) {
		ZAssert.notNull(id, "请选择任务");
		if(Byte.valueOf("5").equals(isOk)) {
			ZAssert.hasText(rejectResaon, "请填写不通过理由");
		}
		return pmpTasksMapper.updateCheck( id,  isOk,  rejectResaon);
	}

}